import cv2
import mediapipe as mp
import math





class NumRecognize:
    def __init__(self):
        # 初始化medialpipe
        self.mp_drawing = mp.solutions.drawing_utils
        self.mp_drawing_styles = mp.solutions.drawing_styles
        self.mp_hands = mp.solutions.hands

    def recognize(self):

        # 获取摄像头
        cap = cv2.VideoCapture(0)
        cap.set(3, 1280)
        cap.set(4, 720)

        # 视频分辨率
        resize_w = 800
        resize_h = 500

        # 画面显示初始化参数
        rect_height = 0
        rect_percent_text = 0

        with self.mp_hands.Hands(min_detection_confidence=0.5,
                                 min_tracking_confidence=0.5,
                                 max_num_hands=2) as hands:
            while True:
                #摄像头打开，读取每一帧图像
                success, image = cap.read()
                image = cv2.resize(image, (resize_w, resize_h))


                # 提高性能
                image.flags.writeable = False
                # 转为RGB
                image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
                # 镜像
                image = cv2.flip(image, 1)
                # mediapipe模型处理
                results = hands.process(image)

                image.flags.writeable = True
                image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

                xList = []
                yList = []
                draw = True

                # 判断是否有手掌
                if results.multi_hand_landmarks:
                    # 遍历每个手掌
                    for handLms in results.multi_hand_landmarks:
                        # 在画面标注手指
                        self.mp_drawing.draw_landmarks(image, handLms,
                                                       self.mp_hands.HAND_CONNECTIONS,
                                                       self.mp_drawing_styles.get_default_hand_landmarks_style(),
                                                       self.mp_drawing_styles.get_default_hand_connections_style())

                        # 解析手指，存入各个手指坐标
                        lmList = []
                        for landmark_id, finger_axis in enumerate(handLms.landmark):
                            lmList.append([
                                landmark_id, finger_axis.x, finger_axis.y,
                                finger_axis.z
                            ])
                            px, py = int(lmList[landmark_id][1] * resize_w), int(
                                lmList[landmark_id][2] * resize_h)  # 比例坐标x乘以宽度得像素x坐标,y乘以高度得到像素y坐标
                            # 存储坐标信息
                            xList.append(px)
                            yList.append(py)
                            xmin, xmax = min(xList), max(xList)
                            ymin, ymax = min(yList), max(yList)
                            boxW, boxH = xmax - xmin, ymax - ymin
                            # 设置bbox左上角的坐标和宽高
                            bbox = xmin, ymin, boxW, boxH
                            # 设置居中时的坐标值
                            cx, cy = bbox[0] + (bbox[2] // 2), \
                                     bbox[1] + (bbox[3] // 2)
                        if draw:
                            # 画矩形框
                            cv2.rectangle(image, (bbox[0] - 20, bbox[1] - 20),
                                          (bbox[0] + bbox[2] + 20, bbox[1] + bbox[3] + 20),
                                          (255, 0, 0), 2)

                        if lmList:
                            # 获取大拇指指尖坐标
                            thumb_finger_tip = lmList[4]
                            thumb_finger_tip_x = math.ceil(thumb_finger_tip[1] * resize_w)
                            thumb_finger_tip_y = math.ceil(thumb_finger_tip[2] * resize_h)
                            # 获取食指指尖坐标
                            index_finger_tip = lmList[8]
                            index_finger_tip_x = math.ceil(index_finger_tip[1] * resize_w)
                            index_finger_tip_y = math.ceil(index_finger_tip[2] * resize_h)
                            # 获取中指指尖坐标
                            middle_finger_tip = lmList[12]
                            middle_finger_tip_x = math.ceil(middle_finger_tip[1] * resize_w)
                            middle_finger_tip_y = math.ceil(middle_finger_tip[2] * resize_h)
                            # 获取无名指指尖坐标
                            ring_finger_tip = lmList[16]
                            ring_finger_tip_x = math.ceil(ring_finger_tip[1] * resize_w)
                            ring_finger_tip_y = math.ceil(ring_finger_tip[2] * resize_h)
                            # 获取小拇指指尖坐标
                            pinky_finger_tip = lmList[20]
                            pinky_finger_tip_x = math.ceil(pinky_finger_tip[1] * resize_w)
                            pinky_finger_tip_y = math.ceil(pinky_finger_tip[2] * resize_h)
                            # 获取pincky_finger_mcp坐标
                            pinky_finger_mcp = lmList[17]
                            pinky_finger_mcp_x = math.ceil(pinky_finger_mcp[1] * resize_w)
                            pinky_finger_mcp_y = math.ceil(pinky_finger_mcp[2] * resize_h)
                            # 获取wrist
                            wrist = lmList[0]
                            wrist_x = math.ceil(wrist[1] * resize_w)
                            wrist_y = math.ceil(wrist[2] * resize_h)
                            # 大拇指指尖到食指指尖距离
                            dist_thumb_index = math.sqrt((index_finger_tip_x-thumb_finger_tip_x)**2
                                                         + (index_finger_tip_y-thumb_finger_tip_y)**2)
                            # 大拇指指尖到中指指尖距离
                            dist_thumb_middle = math.sqrt((middle_finger_tip_x-thumb_finger_tip_x)**2
                                                         + (middle_finger_tip_y-thumb_finger_tip_y)**2)
                            # 大拇指指尖到无名指指尖距离
                            dist_thumb_ring = math.sqrt((ring_finger_tip_x-thumb_finger_tip_x)**2
                                                         + (ring_finger_tip_y-thumb_finger_tip_y)**2)
                            # 大拇指指尖到尾指指尖距离
                            dist_thumb_pinky = math.sqrt((pinky_finger_tip_x-thumb_finger_tip_x)**2
                                                         + (pinky_finger_tip_y-thumb_finger_tip_y)**2)
                            # 大拇指指尖到尾指mcp距离
                            dist_thumb_pinky_mcp = math.sqrt((pinky_finger_mcp_x-thumb_finger_tip_x)**2
                                                         + (pinky_finger_mcp_y-thumb_finger_tip_y)**2)
                            # 无名指指尖到手腕距离
                            dist_ring_tip_wrist = math.sqrt((wrist_x-ring_finger_tip_x)**2
                                                            + (wrist_y-ring_finger_tip_y)**2)
                            # print(dist_thumb_index, dist_thumb_middle, dist_thumb_ring, dist_thumb_pinky, dist_thumb_pinky_mcp, dist_ring_tip_wrist)

                            if((dist_thumb_index >90 ) and (dist_thumb_middle <90 and dist_thumb_ring <90 and dist_thumb_pinky<90 and dist_thumb_pinky_mcp<90)):
                                cv2.putText(image, "1_ONE", (cx, cy),cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)
                            elif ((dist_thumb_index > 90 and dist_thumb_middle > 90) and (dist_thumb_ring < 90 and dist_thumb_pinky < 90 and dist_thumb_pinky_mcp < 90)):
                                cv2.putText(image, "2_TWO", (cx, cy), cv2.FONT_HERSHEY_PLAIN, 3, (0, 0, 255), 3)
                            elif ((dist_thumb_index > 90 and dist_thumb_middle > 90 and dist_thumb_ring > 90) and ( dist_thumb_pinky < 90 and dist_thumb_pinky_mcp < 90)):
                                cv2.putText(image, "3_THREE", (cx, cy), cv2.FONT_HERSHEY_PLAIN, 3, (0, 0, 255), 3)
                            elif ((dist_thumb_index > 90 and dist_thumb_middle > 90 and dist_thumb_ring > 90 and dist_thumb_pinky > 90) and ( dist_thumb_pinky_mcp < 120)):
                                cv2.putText(image, "4_FOUR", (cx, cy), cv2.FONT_HERSHEY_PLAIN, 3, (0, 0, 255), 3)
                            elif ((dist_thumb_index > 90 and dist_thumb_middle > 90 and dist_thumb_ring > 90 and dist_thumb_pinky > 90 and dist_thumb_pinky_mcp > 90) and(dist_ring_tip_wrist>90)):
                                cv2.putText(image, "5_FIVE", (cx, cy), cv2.FONT_HERSHEY_PLAIN, 3, (0, 0, 255), 3)
                            elif ((dist_thumb_index > 90 and dist_thumb_middle > 90 and dist_thumb_ring > 90 and dist_thumb_pinky > 90 and dist_thumb_pinky_mcp > 90) and(dist_ring_tip_wrist<90)):
                                cv2.putText(image, "6_SIX", (cx, cy), cv2.FONT_HERSHEY_PLAIN, 3, (0, 0, 255), 3)
                            elif ((dist_thumb_index < 40) and (dist_thumb_middle > 90 and dist_thumb_ring > 90 and dist_thumb_pinky > 90 and dist_thumb_pinky_mcp > 90)):
                                cv2.putText(image, "OK", (cx, cy), cv2.FONT_HERSHEY_PLAIN, 3, (0, 0, 255), 3)

                # 显示画面
                cv2.imshow('Number Recognize', image)
                if cv2.waitKey(1) & 0xFF == 27:
                    break

            cap.release()


# 开始程序
# control = NumRecognize()
# control.recognize()
